#pragma once
#include <stdio.h>
#include <stdlib.h>
#include "DO.h"
#include "stdafx.h"

namespace efsod {
#define EFSOD_SUCCESS 			0 
#define EFSOD_ERROR 			1
// Hash algorithm for Data Groups not recognized.
#define EFSOD_ERROR_DGHASHALGO 		2
// Hash algorithm for LDSSecurityObject not recognized.
#define EFSOD_ERROR_SODHASHALGO 	3
// Insufficient buffer space for LDSSecurityObject 
#define EFSOD_ERROR_LDS_LEN 		4 
// Insufficient buffer space for DataToSign
#define EFSOD_ERROR_SIGNEDDATA_LEN 	5
// Certificate file not found/readable
#define EFSOD_ERROR_CERT_FILE 		6
// Signature Algorithm not recognized
#define EFSOD_ERROR_SODSIGNALGO 	7

#define SHA1 		0
#define SHA256 		1
#define SHA384 		2
#define SHA512 		3
#define SHA1_LENGTH 	20
#define SHA256_LENGTH 	32
#define SHA384_LENGTH 	48
#define SHA512_LENGTH 	64

typedef struct {
        int DGNum;
        int DGLen;
        BYTE *DGData;
} DG;

typedef struct	{
	const char *algo;
	unsigned long *oid;
	int oidLength;
} algoID;

/*
Object Identifiers for the various allowed hash and signature algorithms
*/
#define sha1idLen 6
static unsigned long sha1id[sha1idLen] = {1,3,14,3,2,26};

#define sha256idLen 9
static unsigned long sha256id[sha256idLen] = {2,16,840,1,101,3,4,2,1};

#define sha384idLen 9
static unsigned long sha384id[sha384idLen] = {2,16,840,1,101,3,4,2,2};

#define sha512idLen 9
static unsigned long sha512id[sha512idLen] = {2,16,840,1,101,3,4,2,3};

#define sha1RSALen 7
static unsigned long sha1RSA[sha1RSALen] = {1,2,840,113549,1,1,5};

#define sha256RSALen 7
static unsigned long sha256RSA[sha256RSALen] = {1,2,840,113549,1,1,11};

#define sha384RSALen 7
static unsigned long sha384RSA[sha384RSALen] = {1,2,840,113549,1,1,12};

#define sha512RSALen 7
static unsigned long sha512RSA[sha512RSALen] = {1,2,840,113549,1,1,13};

#define ldsSOoidLen 8
static unsigned long ldsSOoid[ldsSOoidLen] = {1, 2, 528, 1, 1006, 1, 20, 1};

#define contentTypeoidLen 7
static unsigned long contentTypeoid[contentTypeoidLen] = {1, 2, 840, 113549, 1, 9, 3};

#define msgDigestoidLen 7
static unsigned long msgDigestoid[msgDigestoidLen] = {1, 2, 840, 113549, 1, 9, 4};

#define signedDataoidLen 7
static unsigned long signedDataoid[signedDataoidLen] = {1, 2, 840, 113549, 1, 7, 2};

static BYTE DGNumByte[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D};

/*
List of allowed hash and signature algorithms
*/
static algoID algolist[8] =  {
	{"sha-1", sha1id, sha1idLen},
	{"sha-256", sha256id, sha256idLen},
	{"sha-384", sha384id, sha384idLen},
	{"sha-512", sha512id, sha512idLen},
	{"sha1WithRSAEncryption", sha1RSA, sha1RSALen},
	{"sha256WithRSAEncryption", sha256RSA, sha256RSALen},
	{"sha384WithRSAEncryption", sha384RSA, sha384RSALen},
	{"sha512WithRSAEncryption", sha512RSA, sha512RSALen}
};

//Definitions for the functions
	int createSOD(BYTE *ldsSO, int ldsSOLen, const char *hashAlgoforLDS, const char *cert, BYTE *signedData, int signedDataLen, BYTE *signature, int signLength, const char *signAlgo, BYTE *sod, int *sodLen);
	int createLDSSecurityObject(DG dgs[], int numDG, const char *MDAlgoforDGs, BYTE *ldsSO, int *ldsSOLen, const char *hashAlgoforLDS, BYTE *dataToSign, int *dataToSignLen);

	//EF.COM
static BYTE DGL[5] = {0x61, 0x75, 0x6B, 0x6C, 0x6D};
static BYTE LDS_VERSION[4] = {0x30, 0x31, 0x30, 0x37};
static BYTE UNICODE_VERSION[6] = {0x30, 0x34, 0x30, 0x30, 0x30, 0x30};

#define TAG_EFCOM	0x60
#define TAG_LDS_VERSION	0x5F01
#define TAG_UNICODE_VERSION	0x5F36
#define TAG_DG_LIST	0x5C
#define ERROR_MEM_INSUF	-1
	int createEFCOM(BYTE* ef, int len);

}